﻿using System;
using System.Linq;
using System.Security.Claims;
using System.Security.Principal;
using System.Threading.Tasks;
using IdentityModel.Client;
using JuCheap.SSO.Demo;
using Microsoft.IdentityModel.Protocols;
using Microsoft.Owin;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Cookies;
using Microsoft.Owin.Security.OpenIdConnect;
using Owin;

[assembly: OwinStartup(typeof(Startup))]

namespace JuCheap.SSO.Demo
{
    /// <summary>
    /// Startup
    /// </summary>
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            const string ssoUrl = "http://sso.jucheap.com/identity"; //sso单点登录认证地址,不需要修改
            const string siteUrl = "http://www.aspxpet.com/"; //接入网站的地址
            app.UseCookieAuthentication(new CookieAuthenticationOptions
            {
                AuthenticationType = OpenIdConnectAuthenticationDefaults.AuthenticationType //AuthenticationType必须保持一致
            });
            app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
            {
                Authority = ssoUrl,//SSO服务地址
                ClientId = "C116081708485800001",//必须跟服务端配置的ClientId一致(就是在sso.jucheap.com网站上添加的网站的网站ID)
                Scope = "openid profile roles",
                ResponseType = "id_token token",
                RedirectUri = siteUrl, //登录成功跳转地址=>接入网站地址
                PostLogoutRedirectUri = siteUrl, //登出跳转地址=>接入网站地址
                UseTokenLifetime = false,
                SignInAsAuthenticationType = OpenIdConnectAuthenticationDefaults.AuthenticationType,//AuthenticationType必须保持一致
                Notifications = new OpenIdConnectAuthenticationNotifications
                {
                    SecurityTokenValidated = async n =>
                    {
                        var nid = new ClaimsIdentity(n.AuthenticationTicket.Identity.AuthenticationType, "name", "role");

                        // get userinfo data
                        var userInfoClient = new UserInfoClient(new Uri(n.Options.Authority + "/connect/userinfo"), n.ProtocolMessage.AccessToken);

                        var userInfo = await userInfoClient.GetAsync();
                        userInfo.Claims.ToList().ForEach(ui => nid.AddClaim(new Claim(ui.Item1, ui.Item2)));

                        // keep the id_token for logout
                        nid.AddClaim(new Claim("id_token", n.ProtocolMessage.IdToken));
                        // add access token for sample API
                        nid.AddClaim(new Claim("access_token", n.ProtocolMessage.AccessToken));
                        // keep track of access token expiration
                        nid.AddClaim(new Claim("expires_at", DateTimeOffset.Now.AddSeconds(int.Parse(n.ProtocolMessage.ExpiresIn)).ToString()));

                        nid.AddClaim(new Claim("app_nonce", n.ProtocolMessage.Nonce));

                        n.AuthenticationTicket = new AuthenticationTicket(nid, n.AuthenticationTicket.Properties);
                    },

                    RedirectToIdentityProvider = n =>
                    {
                        if (n.ProtocolMessage.RequestType == OpenIdConnectRequestType.LogoutRequest)
                        {
                            var idTokenHint = n.OwinContext.Authentication.User.FindFirst("id_token");

                            if (idTokenHint != null)
                            {
                                n.ProtocolMessage.IdTokenHint = idTokenHint.Value;
                            }
                        }

                        return Task.FromResult(0);
                    }
                }
            });
        }
    }

    /// <summary>
    /// Identity扩展
    /// </summary>
    public static class IdentityExtentions
    {
        /// <summary>
        /// 获取SSO登录的用户ID
        /// </summary>
        /// <param name="identity"></param>
        /// <returns></returns>
        public static string GetUserId(this IIdentity identity)
        {
            return (identity as ClaimsIdentity)?.FindFirst("sub")?.Value;
        }
    }
}
